#import <UIKit/UIKit.h>
#import "HDJHIDEvent+KIF.h"
#import <mach/mach_time.h>
#import <dlfcn.h>
#import "NSString+Utils64.h"

#define kHDJHIDEventFieldBase(type) (type << 16)
#ifdef __LP64__
typedef double kHDJHIDFloat;
#else
typedef float kHDJHIDFloat;
#endif
typedef UInt32 kHDJOptionBits;
typedef uint32_t HDJHIDDigitizerTransducerType;
typedef uint32_t HDJHIDEventField;
typedef uint32_t HDJHIDEventType;

enum {
    kHDJHIDDigitizerTransducerTypeStylus = 0,
    kHDJHIDDigitizerTransducerTypePuck,
    kHDJHIDDigitizerTransducerTypeFinger,
    kHDJHIDDigitizerTransducerTypeHand
};
enum {
    kHDJHIDEventTypeNULL,                    // 0
    kHDJHIDEventTypeVendorDefined,
    kHDJHIDEventTypeButton,
    kHDJHIDEventTypeKeyboard,
    kHDJHIDEventTypeTranslation,
    kHDJHIDEventTypeRotation,                // 5
    kHDJHIDEventTypeScroll,
    kHDJHIDEventTypeScale,
    kHDJHIDEventTypeZoom,
    kHDJHIDEventTypeVelocity,
    kHDJHIDEventTypeOrientation,             // 10
    kHDJHIDEventTypeDigitizer,
    kHDJHIDEventTypeAmbientLightSensor,
    kHDJHIDEventTypeAccelerometer,
    kHDJHIDEventTypeProximity,
    kHDJHIDEventTypeTemperature,             // 15
    kHDJHIDEventTypeNavigationSwipe,
    kHDJHIDEventTypePointer,
    kHDJHIDEventTypeProgress,
    kHDJHIDEventTypeMultiAxisPointer,
    kHDJHIDEventTypeGyro,                    // 20
    kHDJHIDEventTypeCompass,
    kHDJHIDEventTypeZoomToggle,
    kHDJHIDEventTypeDockSwipe,               // just like kHDJHIDEventTypeNavigationSwipe, but intended for consumption by Dock
    kHDJHIDEventTypeSymbolicHotKey,
    kHDJHIDEventTypePower,                   // 25
    kHDJHIDEventTypeLED,
    kHDJHIDEventTypeFluidTouchGesture,       // This will eventually superseed Navagation and Dock swipes
    kHDJHIDEventTypeBoundaryScroll,
    kHDJHIDEventTypeBiometric,
    kHDJHIDEventTypeUnicode,                 // 30
    kHDJHIDEventTypeAtmosphericPressure,
    kHDJHIDEventTypeUndefined,
    kHDJHIDEventTypeCount, // This should always be last
    // DEPRECATED:
    kHDJHIDEventTypeSwipe = kHDJHIDEventTypeNavigationSwipe,
    kHDJHIDEventTypeMouse = kHDJHIDEventTypePointer
};
enum {
    kHDJHIDDigitizerEventRange                               = 0x00000001,
    kHDJHIDDigitizerEventTouch                               = 0x00000002,
    kHDJHIDDigitizerEventPosition                            = 0x00000004,
    kHDJHIDDigitizerEventStop                                = 0x00000008,
    kHDJHIDDigitizerEventPeak                                = 0x00000010,
    kHDJHIDDigitizerEventIdentity                            = 0x00000020,
    kHDJHIDDigitizerEventAttribute                           = 0x00000040,
    kHDJHIDDigitizerEventCancel                              = 0x00000080,
    kHDJHIDDigitizerEventStart                               = 0x00000100,
    kHDJHIDDigitizerEventResting                             = 0x00000200,
    kHDJHIDDigitizerEventSwipeUp                             = 0x01000000,
    kHDJHIDDigitizerEventSwipeDown                           = 0x02000000,
    kHDJHIDDigitizerEventSwipeLeft                           = 0x04000000,
    kHDJHIDDigitizerEventSwipeRight                          = 0x08000000,
    kHDJHIDDigitizerEventSwipeMask                           = 0xFF000000,
};
enum {
    kHDJHIDEventFieldDigitizerX = kHDJHIDEventFieldBase(kHDJHIDEventTypeDigitizer),
    kHDJHIDEventFieldDigitizerY,
    kHDJHIDEventFieldDigitizerZ,
    kHDJHIDEventFieldDigitizerButtonMask,
    kHDJHIDEventFieldDigitizerType,
    kHDJHIDEventFieldDigitizerIndex,
    kHDJHIDEventFieldDigitizerIdentity,
    kHDJHIDEventFieldDigitizerEventMask,
    kHDJHIDEventFieldDigitizerRange,
    kHDJHIDEventFieldDigitizerTouch,
    kHDJHIDEventFieldDigitizerPressure,
    kHDJHIDEventFieldDigitizerAuxiliaryPressure, //BarrelPressure
    kHDJHIDEventFieldDigitizerTwist,
    kHDJHIDEventFieldDigitizerTiltX,
    kHDJHIDEventFieldDigitizerTiltY,
    kHDJHIDEventFieldDigitizerAltitude,
    kHDJHIDEventFieldDigitizerAzimuth,
    kHDJHIDEventFieldDigitizerQuality,
    kHDJHIDEventFieldDigitizerDensity,
    kHDJHIDEventFieldDigitizerIrregularity,
    kHDJHIDEventFieldDigitizerMajorRadius,
    kHDJHIDEventFieldDigitizerMinorRadius,
    kHDJHIDEventFieldDigitizerCollection,
    kHDJHIDEventFieldDigitizerCollectionChord,
    kHDJHIDEventFieldDigitizerChildEventMask,
    kHDJHIDEventFieldDigitizerIsDisplayIntegrated,
    kHDJHIDEventFieldDigitizerQualityRadiiAccuracy,
};

// 自定义函数名的指针定义
typedef void (*SU9ISURFdmVudEFwcGVuZEV2ZW50_func_pointer) (kHDJHIDEventRef event, kHDJHIDEventRef childEvent);
typedef void (*SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func_pointer) (kHDJHIDEventRef event, HDJHIDEventField field, int value);

typedef kHDJHIDEventRef (*SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50_func_pointer) (CFAllocatorRef allocator,
                                                                      AbsoluteTime timeStamp,
                                                                      HDJHIDDigitizerTransducerType type,
                                                                      uint32_t index,
                                                                      uint32_t identity,
                                                                      uint32_t eventMask,
                                                                      uint32_t buttonMask,
                                                                      kHDJHIDFloat x,
                                                                      kHDJHIDFloat y,
                                                                      kHDJHIDFloat z,
                                                                      kHDJHIDFloat tipPressure,
                                                                      kHDJHIDFloat barrelPressure,
                                                                      Boolean range,
                                                                      Boolean touch,
                                                                      kHDJOptionBits options);

typedef kHDJHIDEventRef (*SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk_func_pointer) (CFAllocatorRef allocator,
                                                                                       AbsoluteTime timeStamp,
                                                                                       uint32_t index,
                                                                                       uint32_t identity,
                                                                                       uint32_t eventMask,
                                                                                       kHDJHIDFloat x,
                                                                                       kHDJHIDFloat y,
                                                                                       kHDJHIDFloat z,
                                                                                       kHDJHIDFloat tipPressure,
                                                                                       kHDJHIDFloat twist,
                                                                                       kHDJHIDFloat minorRadius,
                                                                                       kHDJHIDFloat majorRadius,
                                                                                       kHDJHIDFloat quality,
                                                                                       kHDJHIDFloat density,
                                                                                       kHDJHIDFloat irregularity,
                                                                                       Boolean range,
                                                                                       Boolean touch,
                                                                                       kHDJOptionBits options);


kHDJHIDEventRef kif_HDJHIDEventWithTouches(NSArray *touches) {
    uint64_t abTime = mach_absolute_time();
    AbsoluteTime timeStamp;
    timeStamp.hi = (UInt32)(abTime >> 32);
    timeStamp.lo = (UInt32)(abTime);
    
    //打开动态库
    void *handle = dlopen([NSString char_base64Dencode:@"L1N5c3RlbS9MaWJyYXJ5L0ZyYW1ld29ya3MvSU9LaXQuZnJhbWV3b3JrL0lPS2l0"], RTLD_GLOBAL | RTLD_NOW);

    if (handle == NULL) {
        //打开动态库出错
        fprintf(stderr, "%s\n", dlerror());
        return NULL;
    }

    SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50_func_pointer SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50_func = dlsym(handle, [NSString char_base64Dencode:@"SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50"]);
    kHDJHIDEventRef handEvent = NULL;
    if (SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50_func) {
        handEvent = SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckV2ZW50_func(kCFAllocatorDefault, // allocator 内存分配器
                                            timeStamp, // timestamp 时间戳
                                            kHDJHIDDigitizerTransducerTypeHand, // type
                                            0, // index
                                            0, // identity
                                            kHDJHIDDigitizerEventTouch, // eventMask
                                            0, // buttonMask
                                            0, // x
                                            0, // y
                                            0, // z
                                            0, // tipPressure
                                            0, // barrelPressure
                                            0, // range
                                            true, // touch
                                            0);
    }

    SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func_pointer SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func = dlsym(handle, [NSString char_base64Dencode:@"SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ=="]);
    if (SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func) {
        SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func(handEvent, kHDJHIDEventFieldDigitizerIsDisplayIntegrated, true);
    }

    
    SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk_func_pointer SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk_func = dlsym(handle, [NSString char_base64Dencode:@"SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk="]);
    for (UITouch *touch in touches)
    {
        uint32_t eventMask = (touch.phase == UITouchPhaseMoved) ? kHDJHIDDigitizerEventPosition : (kHDJHIDDigitizerEventRange | kHDJHIDDigitizerEventTouch);
        uint32_t isTouching = (touch.phase == UITouchPhaseEnded) ? 0 : 1;
        CGPoint touchLocation = [touch locationInView:touch.window];
        
        kHDJHIDEventRef fingerEvent = NULL;
        if (SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk_func) {
            fingerEvent = SU9ISURFdmVudENyZWF0ZURpZ2l0aXplckZpbmdlckV2ZW50V2l0aFF1YWxpdHk_func(kCFAllocatorDefault, // allocator
                                                                                        timeStamp, // timestamp
                                                                                        (UInt32)[touches indexOfObject:touch] + 1, //index
                                                                                        2, // identity
                                                                                        eventMask, // eventMask
                                                                                        (kHDJHIDFloat)touchLocation.x, // x
                                                                                        (kHDJHIDFloat)touchLocation.y, // y
                                                                                        0.0, // z
                                                                                        0, // tipPressure
                                                                                        0, // twist
                                                                                        5.0, // minor radius
                                                                                        5.0, // major radius
                                                                                        1.0, // quality
                                                                                        1.0, // density
                                                                                        1.0, // irregularity
                                                                                        (kHDJHIDFloat)isTouching, // range
                                                                                        (kHDJHIDFloat)isTouching, // touch
                                                                                        0); // options
        }

        if (SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func) {
            SU9ISURFdmVudFNldEludGVnZXJWYWx1ZQ_func(fingerEvent, kHDJHIDEventFieldDigitizerIsDisplayIntegrated, 1);
        }

        
        SU9ISURFdmVudEFwcGVuZEV2ZW50_func_pointer SU9ISURFdmVudEFwcGVuZEV2ZW50_func = dlsym(handle, [NSString char_base64Dencode:@"SU9ISURFdmVudEFwcGVuZEV2ZW50"]);
        if (SU9ISURFdmVudEFwcGVuZEV2ZW50_func) {
            SU9ISURFdmVudEFwcGVuZEV2ZW50_func(handEvent, fingerEvent);
        }
        dlclose(handle); //关闭句柄

        CFRelease(fingerEvent);
    }
    return handEvent;
}

